#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>
#include <string>
#include "log.hpp"
#include "udpServer.hpp"

extern Log lg;
extern const size_t BUFFER_SIZE;

struct ThreadInfo
{
    int _sockfd;
    struct sockaddr_in _host;

    ThreadInfo(int sockfd, struct sockaddr_in host)
        :_sockfd(sockfd), _host(host)
    {}
};

void Usage(const std::string proc)
{
    std::cout << "\n\tUsage: " << proc << " serverip serverport\n" << std::endl;
}

void* sendmsg(void* args)
{
    ThreadInfo* ti = static_cast<ThreadInfo*>(args);
    int sockfd = ti->_sockfd;
    struct sockaddr_in server = ti->_host;
    socklen_t len = sizeof(server);
    while(true)
    {
        std::string msg;
        std::cout << "please input@ ";
        getline(std::cin, msg);
        //向服务端发送数据
        ssize_t s = sendto(sockfd, msg.c_str(), msg.size(), 0, (const struct sockaddr*)&server, len);
        if(s < 0) {
            lg(WARNING, "sendto err, errno:%d, errmsg:%s", errno, strerror(errno));
        }
        lg(LOG, "sendto success, errno:%d, errmsg:%s", errno, strerror(errno));
    }
}

void* resvmsg(void* args)
{
    ThreadInfo* ti = static_cast<ThreadInfo*>(args);
    int sockfd = ti->_sockfd;
    struct sockaddr_in server = ti->_host;
    socklen_t len = sizeof(server);
    char buffer[BUFFER_SIZE];
    while(true)
    {
        struct sockaddr_in tmpsock;
        socklen_t tmplen = sizeof(tmpsock);
        //接收从服务端返回的数据
        ssize_t s = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&tmpsock, &tmplen);
        if(s < 0) {
            lg(WARNING, "recvfrom err, errno:%d, errmsg:%s", errno, strerror(errno));
        }
        lg(LOG, "recvfrom success, errno:%d, errmsg:%s", errno, strerror(errno));
        buffer[s] = 0;
        std::cerr << buffer << std::endl;
        //std::cout << buffer << std::endl;
    }
}

// ./udpclient ip port
int main(int argc, char* argv[])
{   
    if(argc != 3) { Usage(argv[0]); exit(0); }
    const char* ip = argv[1];
    int port = atoi(argv[2]);

    //创建套接字
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if(sockfd < 0) {
        lg(FATAL, "socket err, errno:%d, errmsg:%s", errno, strerror(errno));
        exit(1);
    }
    lg(LOG, "socket success, errno:%d, errmsg:%s", errno, strerror(errno));

    //配置目标服务sock
    struct sockaddr_in server;
    bzero(&server, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_port = htons(port);
    server.sin_addr.s_addr = inet_addr(ip);

    ThreadInfo* ti = new ThreadInfo(sockfd, server);

    pthread_t sender, recver;
    // 发送消息线程
    pthread_create(&sender, nullptr, sendmsg, (void*)ti);
    // 接收消息线程
    pthread_create(&recver, nullptr, resvmsg, (void*)ti);

    pthread_join(recver, nullptr);
    pthread_join(sender, nullptr);

    close(sockfd);
    return 0;
}